import os
import sys
import re
import logging

from google.appengine.ext import db

from glog import AppEnv
from glog.base import Error
from glog import utils

# theme page ids
EditPost_page = 'EditPost.page'
PostList_page = 'PostList.page'
PostSummary_page = 'PostSummary.page'
Settings_page = 'Settings.page'
ShowError_page = 'ShowError.page'
ViewPost_page = 'ViewPost.page'

__themepageids__ = [
    EditPost_page,
    PostList_page,
    PostSummary_page,
    Settings_page,
    ShowError_page,
    ViewPost_page,
    ]

# system page ids
AppNotInit_page = 'AppNotInit.page'
AppInit_page = 'AppInit.page'
AdminApp_page = 'AdminApp.page'
AdminThemes_page = 'AdminThemes.page'
AppIndex_page = 'AppIndex.page'
FailedPingEcho_xml = 'FailedPingEcho.xml'
SucceedPingEcho_xml = 'SucceedPingEcho.xml'
NewUser_mail = 'NewUser.mail'

class Theme(db.Model):
    name = db.StringProperty(default='default')
    
def initAllThemes():
    server_path = os.path.normpath(os.path.join(AppEnv.app_root, 'template'))
    if not os.path.exists(server_path):
        raise Error.ThemePathNotAvailableError()
    gr = os.walk(server_path)
    for d in gr.next()[1]:
        if not d.startswith('.'):
            create(d)

def getAvailableThemes():
    """Get list of available themes.
    Available theme must have the same directory name in both template dir and themes dir.
    We can not chech the static_dir themes now by gae, limited by the runtime ristrict.
    """    
    server_path = os.path.normpath(os.path.join(AppEnv.app_root, 'template'))
    templateset = set([k for k in os.walk(server_path).next()[1] if not k.startswith('.')])
    #server_path = os.path.normpath(os.path.join(AppEnv.app_root, 'themes'))
    #themesset = set([k for k in os.walk(server_path).next()[1] if not k.startswith('.')])
    existsset = set([t.name for t in Theme.all().fetch(limit=1000)])
    #return list((templateset & themesset)-existsset)
    return list(templateset-existsset)
    
def create(name):
    theme = Theme.get_by_key_name(name)
    if theme:
        raise  Error.ObjectExistsError('Theme [%s] has exists.' % name)
    
    server_path = os.path.normpath(os.path.join(AppEnv.app_root, 'template', name))
    if not os.path.exists(server_path):
        raise Error.ThemePathNotAvailableError()
    # check integrition
    for page in __themepageids__:
        filepath = os.path.join(server_path, page)
        if not os.path.exists(filepath):
            raise Error.ThemeNotIntegrityError('Theme %s is not integrity. %s is missing' % (name,page))

    theme = Theme(key_name = name,
                  name = name)
    theme.put()
    return theme

def delete_theme(name):
    if name == 'default':
        raise Exception('[default] theme can not be delete.')
    
    theme = Theme.get_by_key_name(name)
    if theme:
        defaultTheme = getDefaultTheme()
        import Blog
        blogs = Blog.Blog.all().filter('theme = ', theme).fetch(limit=1000)
        while blogs:
            for blog in blogs:
                blog.theme = defaultTheme
                blog.put()
            blogs = Blog.Blog.all().filter('theme = ', theme).fetch(limit=1000)
        theme.delete()
    else:
        raise Error.NoThisObjectError()
    
def getDefaultTheme():
    theme = Theme.get_by_key_name('default')
    if not theme:
        raise Error.NoDefaultThemeError()
    else:
        return theme
    
def getTheme(name):
    theme = Theme.get_by_key_name(name)
    if not theme:
        raise Error.NoThisObjectError()
    else:
        return theme
    
def getAllThemes():
    return Theme.all().fetch(limit=1000)
    
__themeName_re__ = re.compile(r'^\w{6,30}$')
def checkname(s):
    # must be regex r'\w'
    if not __themeName_re__.match(s):
        return False, 'Theme name must be 6-30 bit number or English charactors.'
    return True, None

def checkAll(name):
    cl = [
        checkname(name),
          ]
    return all([cr[0] for cr in cl]),[cr[1] for cr in cl if not cr[0]]

